/**
 * @module utils/LayerUtil
 * @desc 图层工具
 */

import { randomUUID } from '../../../mapUtils/RandomUtil';
import Layer from '../constant/Layer';

/**
 * 展示全类型图层
 * @param {ITool} self 地图工具箱
 */
export function showFullLayer(self) {
  self._layerIdsAll.forEach((layerid) => {
    self.getMap().setLayoutProperty(layerid, 'visibility', 'visible');
  });
}

/**
 * 隐藏全类型图层
 * @param {ITool} self 地图工具箱
 */
export function hideFullLayer(self) {
  self._layerIdsAll.forEach((layerid) => {
    self.getMap().setLayoutProperty(layerid, 'visibility', 'none');
  });
}

/**
 * 清空全类型图层
 * @param {ITool} self 地图工具箱
 */
export function clearFullLayer(self) {
  self.getMap()
    .getSource(self._sourceId)
    .setData(turf.featureCollection([]));
}

/**
 * 删除全类型图层
 * @param {ITool} self 地图工具箱
 */
export function removeFullLayer(self) {
  self._layerIdsAll.forEach((layerid) => {
    self.getMap().removeLayer(layerid);
  });
  self.getMap().removeSource(self._sourceId);
}


/**
 * 向地理数据模型属性中添加文字标签属性
 * @param {*} features 地理数据
 * @param {*} name 文字标签名称
 */
export function addTextFieldPropertiesToFeatures(features, name) {
  features.forEach((item) => {
    item.properties[Layer.GlobalMarkLabelField] = item.properties[name];
  });
  return features;
}

/**
 * 设置图层属性
 * @param {*} layerinfo 图层
 * @param {*} meta 属性
 */
export function injectLayerMeta(layerinfo, meta) {
  layerinfo.metadata = meta;
  return layerinfo;
}

/**
 * 将点模型转换为正方形模型
 * @param {*} point
 * @param {*} buffer
 */
function pointToBoundingBox(point, buffer = 0) {
  return [
    [point.x - buffer, point.y - buffer],
    [point.x + buffer, point.y + buffer]
  ];
}

/**
 * 初始化图层Id
 * @param {ITool} self 地图工具箱
 */
function _initId(self) {
  self.id = self.id || randomUUID();
  let prefix = self.layeridPrefix ? self.layeridPrefix + '_' : '';
  self._layerMarkerId = prefix + 'Marker' + self.id;
  self._layerPointId = prefix + 'Point' + self.id;
  self._layerLinestringId = prefix + 'LineString' + self.id;
  self._layerMultilinestringId = prefix + 'MultiLineString' + self.id;
  self._layerPolygonId = prefix + 'Polygon' + self.id;
  self._layerMultipolygonId = prefix + 'MultiPolygon' + self.id;
  self._layerLinestringtextId = prefix + 'LineStringText' + self.id;
  self._layerMultilinestringtextId = prefix + 'MultiLineStringText' + self.id;
  // 数据源
  self._sourceId = prefix + 'source_' + self.id;
  self._layerIds = [
    self._layerPolygonId,
    self._layerMultipolygonId,
    self._layerLinestringId,
    self._layerMultilinestringId,
    self._layerPointId,
    self._layerMarkerId
  ];
  self._layerIdsAll = self._layerIds.concat([self._layerLinestringtextId, self._layerMultilinestringtextId]);
}

/**
 * 初始化数据源
 * @param {ITool} self 地图工具箱
 */
function _initSource(self) {
  if(!self.getMap().getSource(self._sourceId)) {
    self.getMap().addSource(self._sourceId, {
      type: 'geojson',
      data: {
        type: 'FeatureCollection',
        features: []
      }
    });
  }
}

/**
 * 初始化图层
 * @param {ITool} self 地图工具箱
 */
function _initLayers(self) {
  // polygon
  if(!self.getMap().getLayer(self._layerPolygonId)) {
    self.getMap().addLayer(
      injectLayerMeta(
        {
          id: self._layerPolygonId,
          type: 'fill',
          source: self._sourceId,
          filter: ['all', ['==', 'sourceType', 'Polygon']],
          paint: {
            'fill-color': ['get', 'color'],
            'fill-opacity': ['get', 'opacity']
          }
        },
        { filter: ['all', ['==', 'sourceType', 'Polygon']] }
      )
    );
  }
  // multi polygon
  if(!self.getMap().getLayer(self._layerMultipolygonId)) {
    self.getMap().addLayer(
      injectLayerMeta(
        {
          id: self._layerMultipolygonId,
          type: 'fill',
          source: self._sourceId,
          filter: ['all', ['==', 'sourceType', 'MultiPolygon']],
          paint: {
            'fill-color': ['get', 'color'],
            'fill-opacity': ['get', 'opacity']
          }
        },
        { filter: ['all', ['==', 'sourceType', 'MultiPolygon']] }
      )
    );
  }
  // linestring
  if(!self.getMap().getLayer(self._layerLinestringId)) {
    self.getMap().addLayer(
      injectLayerMeta(
        {
          id: self._layerLinestringId,
          type: 'line',
          source: self._sourceId,
          filter: ['all', ['==', 'sourceType', 'LineString']],
          layout: {
            'line-cap': 'round',
            'line-join': 'round'
          },
          paint: {
            'line-color': ['get', 'color'],
            'line-width': ['get', 'width'],
            'line-opacity': ['get', 'opacity'],
            'line-offset': 0
          }
        },
        { filter: ['all', ['==', 'sourceType', 'LineString']] }
      )
    );
  }
  // multi linestring
  if(!self.getMap().getLayer(self._layerMultilinestringId)) {
    self.getMap().addLayer(
      injectLayerMeta(
        {
          id: self._layerMultilinestringId,
          type: 'line',
          source: self._sourceId,
          filter: ['all', ['==', 'sourceType', 'MultiLineString']],
          layout: {
            'line-cap': 'round',
            'line-join': 'round'
          },
          paint: {
            'line-color': ['get', 'color'],
            'line-width': ['get', 'width'],
            'line-opacity': ['get', 'opacity'],
            'line-offset': 0
          }
        },
        { filter: ['all', ['==', 'sourceType', 'MultiLineString']] }
      )
    );
  }
  // linestring-text
  if(!self.getMap().getLayer(self._layerLinestringtextId)) {
    self.getMap().addLayer(
      injectLayerMeta(
        {
          id: self._layerLinestringtextId,
          type: 'symbol',
          source: self._sourceId,
          filter: ['all', ['==', 'sourceType', 'LineString']],
          layout: {
            'symbol-placement': 'line',
            'icon-ignore-placement': true,
            'icon-anchor': 'center',
            'text-field': '{' + Layer.GlobalMarkLabelField + '}',
            'text-size': 12,
            'text-font': ['Microsoft YaHei Regular'],
            'text-offset': [0, 0],
            'text-max-width': 8,
            'text-allow-overlap': false,
            'text-ignore-placement': false
          },
          paint: {
            'text-color': ['get', 'color'],
            'text-halo-color': '#FFFFFF',
            'text-halo-width': 1.33333
          }
        },
        { filter: ['all', ['==', 'sourceType', 'LineString']] }
      )
    );
  }
  // multi linestring-text
  if(!self.getMap().getLayer(self._layerMultilinestringtextId)) {
    self.getMap().addLayer(
      injectLayerMeta(
        {
          id: self._layerMultilinestringtextId,
          type: 'symbol',
          source: self._sourceId,
          filter: ['all', ['==', 'sourceType', 'MultiLineString']],
          layout: {
            'symbol-placement': 'line',
            'icon-ignore-placement': true,
            'icon-anchor': 'center',
            'text-field': '{' + Layer.GlobalMarkLabelField + '}',
            'text-size': 12,
            'text-font': ['Microsoft YaHei Regular'],
            'text-offset': [0, 0],
            'text-max-width': 8,
            'text-allow-overlap': false,
            'text-ignore-placement': false
          },
          paint: {
            'text-color': ['get', 'color'],
            'text-halo-color': '#FFFFFF',
            'text-halo-width': 1.33333
          }
        },
        { filter: ['all', ['==', 'sourceType', 'MultiLineString']] }
      )
    );
  }
  // point
  if(!self.getMap().getLayer(self._layerPointId)) {
    self.getMap().addLayer(
      injectLayerMeta(
        {
          id: self._layerPointId,
          type: 'circle',
          source: self._sourceId,
          filter: ['all', ['==', 'sourceType', 'Point']],
          paint: {
            'circle-radius': ['get', 'size'],
            'circle-color': ['get', 'color'],
            'circle-stroke-color': ['get', 'outlineColor'],
            'circle-stroke-width': ['get', 'outlineWidth'],
            'circle-opacity': ['get', 'opacity']
          }
        },
        { filter: ['all', ['==', 'sourceType', 'Point']] }
      )
    );
  }
  // marker
  if(!self.getMap().getLayer(self._layerMarkerId)) {
    self.getMap().addLayer(
      injectLayerMeta(
        {
          id: self._layerMarkerId,
          type: 'symbol',
          source: self._sourceId,
          filter: ['all', ['==', 'sourceType', 'Marker']],
          layout: {
            'icon-image': '{icon}',
            'icon-size': ['get', 'iconSize'],
            'icon-allow-overlap': true,
            'icon-ignore-placement': true,
            'icon-anchor': 'center',
            'text-field': '{' + Layer.GlobalMarkLabelField + '}',
            'text-size': 12,
            'text-font': ['Microsoft YaHei Regular'],
            'text-offset': [0, 1],
            'text-allow-overlap': false,
            'text-ignore-placement': false,
            'text-optional': true
          },
          paint: {
            'text-color': ['get', 'textColor']
          }
        },
        { filter: ['all', ['==', 'sourceType', 'Marker']] }
      )
    );
  }
}

/**
 * 初始化全类型图层
 * @param {ITool} self 地图工具箱
 */
export function initFullLayer(self) {
  _initId(self);
  _initSource(self);
  _initLayers(self);
}

/**
 * 图层事件回调
 * @param {*} event 图层事件
 * @param {*} e 事件参数
 * @param {*} features 地理数据模型
 * @ignore
 */
function _doCallback(event, e, features) {
  if (features.length > 0) {
    // 点击屏幕坐标
    let point = [e.point.x, e.point.y];
    // 点击地图坐标
    let lngLat = e.lngLat.toArray();
    if(event) {
      event(
        features.map((feature) => {
          return {
            type: 'Feature',
            layer: feature.layer,
            properties: feature.properties,
            geometry: feature.geometry,
            point,
            lngLat
          };
        })
      );
    }
  }
}

/**
 * 全类型图层事件绑定
 * @param {ITool} self 地图工具箱
 */
export function initFullEvents(self) {
  // 点击
  self.getMap().on('click', (e) => {
    let features = self.getMap().queryRenderedFeatures(pointToBoundingBox(e.point, 3), { layers: self._layerIds });
    _doCallback(self.events.click, e, features);
  });
  // 双击
  self.getMap().on('dblclick', (e) => {
    let features = self.getMap().queryRenderedFeatures(pointToBoundingBox(e.point, 3), { layers: self._layerIds });
    _doCallback(self.events.dblclick, e, features);
  });
  // 移动时，检测鼠标下是否有元素，触发mouseover事件
  self.getMap().on('mousemove', (e) => {
    let features = self.getMap().queryRenderedFeatures(pointToBoundingBox(e.point, 3), { layers: self._layerIds });
    if (features.length > 0) {
      _doCallback(self.events.mouseover, e, features);
    } else if(self.events.mouseout) {
      self.events.mouseout();
    }
  });
}